/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package it.polimi.games.epkb.controller;

import it.polimi.games.epkb.controller.exceptions.NonexistentEntityException;
import it.polimi.games.epkb.controller.exceptions.PreexistingEntityException;
import it.polimi.games.epkb.entityClasses.VirtualMachineConf;
import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import it.polimi.games.epkb.entityClasses.Service;
import java.util.ArrayList;
import java.util.Collection;
import it.polimi.games.epkb.entityClasses.Annotation;
import it.polimi.games.epkb.entityClasses.VirtualMachineInst;
import javax.transaction.UserTransaction;

/**
 *
 * @author plebani
 */
public class VirtualMachineConfJpaController implements Serializable {

    public VirtualMachineConfJpaController(EntityManagerFactory emf) {
        this.utx = null;
        this.emf = emf;
    }

    public VirtualMachineConfJpaController(UserTransaction utx, EntityManagerFactory emf) {
        this.utx = utx;
        this.emf = emf;
    }
    private UserTransaction utx = null;
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(VirtualMachineConf virtualMachineConf) throws PreexistingEntityException, Exception {
        if (virtualMachineConf.getServiceCollection() == null) {
            virtualMachineConf.setServiceCollection(new ArrayList<Service>());
        }
        if (virtualMachineConf.getAnnotationCollection() == null) {
            virtualMachineConf.setAnnotationCollection(new ArrayList<Annotation>());
        }
        if (virtualMachineConf.getVirtualMachineInstCollection() == null) {
            virtualMachineConf.setVirtualMachineInstCollection(new ArrayList<VirtualMachineInst>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Collection<Service> attachedServiceCollection = new ArrayList<Service>();
            for (Service serviceCollectionServiceToAttach : virtualMachineConf.getServiceCollection()) {
                serviceCollectionServiceToAttach = em.getReference(serviceCollectionServiceToAttach.getClass(), serviceCollectionServiceToAttach.getId());
                attachedServiceCollection.add(serviceCollectionServiceToAttach);
            }
            virtualMachineConf.setServiceCollection(attachedServiceCollection);
            Collection<Annotation> attachedAnnotationCollection = new ArrayList<Annotation>();
            for (Annotation annotationCollectionAnnotationToAttach : virtualMachineConf.getAnnotationCollection()) {
                annotationCollectionAnnotationToAttach = em.getReference(annotationCollectionAnnotationToAttach.getClass(), annotationCollectionAnnotationToAttach.getId());
                attachedAnnotationCollection.add(annotationCollectionAnnotationToAttach);
            }
            virtualMachineConf.setAnnotationCollection(attachedAnnotationCollection);
            Collection<VirtualMachineInst> attachedVirtualMachineInstCollection = new ArrayList<VirtualMachineInst>();
            for (VirtualMachineInst virtualMachineInstCollectionVirtualMachineInstToAttach : virtualMachineConf.getVirtualMachineInstCollection()) {
                virtualMachineInstCollectionVirtualMachineInstToAttach = em.getReference(virtualMachineInstCollectionVirtualMachineInstToAttach.getClass(), virtualMachineInstCollectionVirtualMachineInstToAttach.getId());
                attachedVirtualMachineInstCollection.add(virtualMachineInstCollectionVirtualMachineInstToAttach);
            }
            virtualMachineConf.setVirtualMachineInstCollection(attachedVirtualMachineInstCollection);
            em.persist(virtualMachineConf);
            for (Service serviceCollectionService : virtualMachineConf.getServiceCollection()) {
                serviceCollectionService.getVirtualMachineConfCollection().add(virtualMachineConf);
                serviceCollectionService = em.merge(serviceCollectionService);
            }
            for (Annotation annotationCollectionAnnotation : virtualMachineConf.getAnnotationCollection()) {
                VirtualMachineConf oldIdVirtualMachineConfOfAnnotationCollectionAnnotation = annotationCollectionAnnotation.getIdVirtualMachineConf();
                annotationCollectionAnnotation.setIdVirtualMachineConf(virtualMachineConf);
                annotationCollectionAnnotation = em.merge(annotationCollectionAnnotation);
                if (oldIdVirtualMachineConfOfAnnotationCollectionAnnotation != null) {
                    oldIdVirtualMachineConfOfAnnotationCollectionAnnotation.getAnnotationCollection().remove(annotationCollectionAnnotation);
                    oldIdVirtualMachineConfOfAnnotationCollectionAnnotation = em.merge(oldIdVirtualMachineConfOfAnnotationCollectionAnnotation);
                }
            }
            for (VirtualMachineInst virtualMachineInstCollectionVirtualMachineInst : virtualMachineConf.getVirtualMachineInstCollection()) {
                VirtualMachineConf oldIdVMConfOfVirtualMachineInstCollectionVirtualMachineInst = virtualMachineInstCollectionVirtualMachineInst.getIdVMConf();
                virtualMachineInstCollectionVirtualMachineInst.setIdVMConf(virtualMachineConf);
                virtualMachineInstCollectionVirtualMachineInst = em.merge(virtualMachineInstCollectionVirtualMachineInst);
                if (oldIdVMConfOfVirtualMachineInstCollectionVirtualMachineInst != null) {
                    oldIdVMConfOfVirtualMachineInstCollectionVirtualMachineInst.getVirtualMachineInstCollection().remove(virtualMachineInstCollectionVirtualMachineInst);
                    oldIdVMConfOfVirtualMachineInstCollectionVirtualMachineInst = em.merge(oldIdVMConfOfVirtualMachineInstCollectionVirtualMachineInst);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findVirtualMachineConf(virtualMachineConf.getId()) != null) {
                throw new PreexistingEntityException("VirtualMachineConf " + virtualMachineConf + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(VirtualMachineConf virtualMachineConf) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            VirtualMachineConf persistentVirtualMachineConf = em.find(VirtualMachineConf.class, virtualMachineConf.getId());
            Collection<Service> serviceCollectionOld = persistentVirtualMachineConf.getServiceCollection();
            Collection<Service> serviceCollectionNew = virtualMachineConf.getServiceCollection();
            Collection<Annotation> annotationCollectionOld = persistentVirtualMachineConf.getAnnotationCollection();
            Collection<Annotation> annotationCollectionNew = virtualMachineConf.getAnnotationCollection();
            Collection<VirtualMachineInst> virtualMachineInstCollectionOld = persistentVirtualMachineConf.getVirtualMachineInstCollection();
            Collection<VirtualMachineInst> virtualMachineInstCollectionNew = virtualMachineConf.getVirtualMachineInstCollection();
            Collection<Service> attachedServiceCollectionNew = new ArrayList<Service>();
            for (Service serviceCollectionNewServiceToAttach : serviceCollectionNew) {
                serviceCollectionNewServiceToAttach = em.getReference(serviceCollectionNewServiceToAttach.getClass(), serviceCollectionNewServiceToAttach.getId());
                attachedServiceCollectionNew.add(serviceCollectionNewServiceToAttach);
            }
            serviceCollectionNew = attachedServiceCollectionNew;
            virtualMachineConf.setServiceCollection(serviceCollectionNew);
            Collection<Annotation> attachedAnnotationCollectionNew = new ArrayList<Annotation>();
            for (Annotation annotationCollectionNewAnnotationToAttach : annotationCollectionNew) {
                annotationCollectionNewAnnotationToAttach = em.getReference(annotationCollectionNewAnnotationToAttach.getClass(), annotationCollectionNewAnnotationToAttach.getId());
                attachedAnnotationCollectionNew.add(annotationCollectionNewAnnotationToAttach);
            }
            annotationCollectionNew = attachedAnnotationCollectionNew;
            virtualMachineConf.setAnnotationCollection(annotationCollectionNew);
            Collection<VirtualMachineInst> attachedVirtualMachineInstCollectionNew = new ArrayList<VirtualMachineInst>();
            for (VirtualMachineInst virtualMachineInstCollectionNewVirtualMachineInstToAttach : virtualMachineInstCollectionNew) {
                virtualMachineInstCollectionNewVirtualMachineInstToAttach = em.getReference(virtualMachineInstCollectionNewVirtualMachineInstToAttach.getClass(), virtualMachineInstCollectionNewVirtualMachineInstToAttach.getId());
                attachedVirtualMachineInstCollectionNew.add(virtualMachineInstCollectionNewVirtualMachineInstToAttach);
            }
            virtualMachineInstCollectionNew = attachedVirtualMachineInstCollectionNew;
            virtualMachineConf.setVirtualMachineInstCollection(virtualMachineInstCollectionNew);
            virtualMachineConf = em.merge(virtualMachineConf);
            for (Service serviceCollectionOldService : serviceCollectionOld) {
                if (!serviceCollectionNew.contains(serviceCollectionOldService)) {
                    serviceCollectionOldService.getVirtualMachineConfCollection().remove(virtualMachineConf);
                    serviceCollectionOldService = em.merge(serviceCollectionOldService);
                }
            }
            for (Service serviceCollectionNewService : serviceCollectionNew) {
                if (!serviceCollectionOld.contains(serviceCollectionNewService)) {
                    serviceCollectionNewService.getVirtualMachineConfCollection().add(virtualMachineConf);
                    serviceCollectionNewService = em.merge(serviceCollectionNewService);
                }
            }
            for (Annotation annotationCollectionOldAnnotation : annotationCollectionOld) {
                if (!annotationCollectionNew.contains(annotationCollectionOldAnnotation)) {
                    annotationCollectionOldAnnotation.setIdVirtualMachineConf(null);
                    annotationCollectionOldAnnotation = em.merge(annotationCollectionOldAnnotation);
                }
            }
            for (Annotation annotationCollectionNewAnnotation : annotationCollectionNew) {
                if (!annotationCollectionOld.contains(annotationCollectionNewAnnotation)) {
                    VirtualMachineConf oldIdVirtualMachineConfOfAnnotationCollectionNewAnnotation = annotationCollectionNewAnnotation.getIdVirtualMachineConf();
                    annotationCollectionNewAnnotation.setIdVirtualMachineConf(virtualMachineConf);
                    annotationCollectionNewAnnotation = em.merge(annotationCollectionNewAnnotation);
                    if (oldIdVirtualMachineConfOfAnnotationCollectionNewAnnotation != null && !oldIdVirtualMachineConfOfAnnotationCollectionNewAnnotation.equals(virtualMachineConf)) {
                        oldIdVirtualMachineConfOfAnnotationCollectionNewAnnotation.getAnnotationCollection().remove(annotationCollectionNewAnnotation);
                        oldIdVirtualMachineConfOfAnnotationCollectionNewAnnotation = em.merge(oldIdVirtualMachineConfOfAnnotationCollectionNewAnnotation);
                    }
                }
            }
            for (VirtualMachineInst virtualMachineInstCollectionOldVirtualMachineInst : virtualMachineInstCollectionOld) {
                if (!virtualMachineInstCollectionNew.contains(virtualMachineInstCollectionOldVirtualMachineInst)) {
                    virtualMachineInstCollectionOldVirtualMachineInst.setIdVMConf(null);
                    virtualMachineInstCollectionOldVirtualMachineInst = em.merge(virtualMachineInstCollectionOldVirtualMachineInst);
                }
            }
            for (VirtualMachineInst virtualMachineInstCollectionNewVirtualMachineInst : virtualMachineInstCollectionNew) {
                if (!virtualMachineInstCollectionOld.contains(virtualMachineInstCollectionNewVirtualMachineInst)) {
                    VirtualMachineConf oldIdVMConfOfVirtualMachineInstCollectionNewVirtualMachineInst = virtualMachineInstCollectionNewVirtualMachineInst.getIdVMConf();
                    virtualMachineInstCollectionNewVirtualMachineInst.setIdVMConf(virtualMachineConf);
                    virtualMachineInstCollectionNewVirtualMachineInst = em.merge(virtualMachineInstCollectionNewVirtualMachineInst);
                    if (oldIdVMConfOfVirtualMachineInstCollectionNewVirtualMachineInst != null && !oldIdVMConfOfVirtualMachineInstCollectionNewVirtualMachineInst.equals(virtualMachineConf)) {
                        oldIdVMConfOfVirtualMachineInstCollectionNewVirtualMachineInst.getVirtualMachineInstCollection().remove(virtualMachineInstCollectionNewVirtualMachineInst);
                        oldIdVMConfOfVirtualMachineInstCollectionNewVirtualMachineInst = em.merge(oldIdVMConfOfVirtualMachineInstCollectionNewVirtualMachineInst);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                String id = virtualMachineConf.getId();
                if (findVirtualMachineConf(id) == null) {
                    throw new NonexistentEntityException("The virtualMachineConf with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(String id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            VirtualMachineConf virtualMachineConf;
            try {
                virtualMachineConf = em.getReference(VirtualMachineConf.class, id);
                virtualMachineConf.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The virtualMachineConf with id " + id + " no longer exists.", enfe);
            }
            Collection<Service> serviceCollection = virtualMachineConf.getServiceCollection();
            for (Service serviceCollectionService : serviceCollection) {
                serviceCollectionService.getVirtualMachineConfCollection().remove(virtualMachineConf);
                serviceCollectionService = em.merge(serviceCollectionService);
            }
            Collection<Annotation> annotationCollection = virtualMachineConf.getAnnotationCollection();
            for (Annotation annotationCollectionAnnotation : annotationCollection) {
                annotationCollectionAnnotation.setIdVirtualMachineConf(null);
                annotationCollectionAnnotation = em.merge(annotationCollectionAnnotation);
            }
            Collection<VirtualMachineInst> virtualMachineInstCollection = virtualMachineConf.getVirtualMachineInstCollection();
            for (VirtualMachineInst virtualMachineInstCollectionVirtualMachineInst : virtualMachineInstCollection) {
                virtualMachineInstCollectionVirtualMachineInst.setIdVMConf(null);
                virtualMachineInstCollectionVirtualMachineInst = em.merge(virtualMachineInstCollectionVirtualMachineInst);
            }
            em.remove(virtualMachineConf);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<VirtualMachineConf> findVirtualMachineConfEntities() {
        return findVirtualMachineConfEntities(true, -1, -1);
    }

    public List<VirtualMachineConf> findVirtualMachineConfEntities(int maxResults, int firstResult) {
        return findVirtualMachineConfEntities(false, maxResults, firstResult);
    }

    private List<VirtualMachineConf> findVirtualMachineConfEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(VirtualMachineConf.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public VirtualMachineConf findVirtualMachineConf(String id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(VirtualMachineConf.class, id);
        } finally {
            em.close();
        }
    }

    public int getVirtualMachineConfCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<VirtualMachineConf> rt = cq.from(VirtualMachineConf.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
